home *** CD-ROM | disk | FTP | other *** search
/ CD ROM Paradise Collection 4 / CD ROM Paradise Collection 4 1995 Nov.iso / ghostscr / gsview07.zip / gsview.c < prev    next >
C/C++ Source or Header  |  1993-05-10  |  36KB  |  1,247 lines

  1. /*
  2.  * gsview.c -- Main module of GSVIEW.EXE, a graphical interface for 
  3.  *             MS-Windows Ghostscript
  4.  * Copyright (C) 1993  Russell Lang
  5.  *
  6.  * This program is free software; you can redistribute it and/or modify
  7.  * it under the terms of the GNU General Public License as published by
  8.  * the Free Software Foundation; either version 2 of the License, or
  9.  * (at your option) any later version.
  10.  *
  11.  * This program is distributed in the hope that it will be useful,
  12.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14.  * GNU General Public License for more details.
  15.  *
  16.  * You should have received a copy of the GNU General Public License
  17.  * along with this program; if not, write to the Free Software
  18.  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  19.  *
  20.  *   Author: Russell Lang
  21.  * Internet: rjl@monu1.cc.monash.edu.au
  22.  */
  23.  
  24. #define STRICT
  25. #include <windows.h>
  26. #include <windowsx.h>
  27. #include <commdlg.h>
  28. #include <shellapi.h>
  29. #include <mmsystem.h>
  30. #include <stdio.h>
  31. #include <stdlib.h>
  32. #include <string.h>
  33. #include <ctype.h>
  34. #include <dir.h>
  35. #define NeedFunctionPrototypes 1
  36. #include "ps.h"
  37. #include "gsview.h"
  38.  
  39. char szAppName[MAXSTR];            /* application name - for title bar */
  40. const char szClassName[] = "gsview_class";
  41. const char szScratch[] = "gsview";    /* temporary filename prefix */
  42.  
  43. HWND hwndimg;            /* gsview main window */
  44. HWND hDlgModeless;        /* any modeless dialog box */
  45. HWND hwndtext;            /* gswin text window */
  46. HWND hwndimgchild;        /* gswin image child window */
  47. HINSTANCE phInstance;        /* instance of gsview */
  48. HINSTANCE gswin_hinst;        /* instance of gswin */
  49. int bitmap_scrollx=0;        /* offset from bitmap to origin of child window */
  50. int bitmap_scrolly=0;
  51. int bitmap_width;        /* size of gswin bitmap in pixels */
  52. int bitmap_height;
  53.  
  54. /* these can be saved in the INI file */
  55. char szGSwin[128];        /* command to invoke gswin */
  56. POINT img_origin;        /* gsview window origin */
  57. POINT img_size;            /* gsview window size */
  58. BOOL quick;            /* use quick opening (don't reload gswin) */
  59. BOOL settings;            /* save settings on exit */
  60. BOOL button_show;        /* show buttons bar */
  61. int media;            /* IDM_LETTER etc. */
  62. int user_width, user_height;    /* User Defined media size */
  63. BOOL epsf_clip;            /* make bitmap size of epsf bounding box */
  64. BOOL epsf_warn;            /* write warning messages if operators incompatible with EPS are used */
  65. BOOL redisplay;            /* redisplay on resize */
  66. int orientation;        /* IDM_PORTRAIT, IDM_LANDSCAPE etc. */
  67. BOOL swap_landscape;        /* swap IDM_LANDSCAPE & IDM_SEASCAPE */
  68. float xdpi, ydpi;        /* resolution of gswin bitmap */
  69. UINT timeout;            /* default timeout period in 1 sec units */
  70. BOOL save_dir;            /* remember current directory for next time */
  71. char device_name[32];        /* printer name */
  72. char device_resolution[32];    /* printer resolution */
  73.  
  74. struct sound_s sound[NUMSOUND] = {
  75.     {"SoundOutputPage", IDS_SNDPAGE, ""},
  76.     {"SoundNoPage", IDS_SNDNOPAGE, BEEP},
  77.     {"SoundNoNumbering", IDS_SNDNONUMBER, ""},
  78.     {"SoundNotOpen", IDS_SNDNOTOPEN, ""},
  79.     {"SoundError", IDS_SNDERROR, BEEP},
  80.     {"SoundTimeout", IDS_SNDTIMEOUT, ""},
  81.     {"SoundStart", IDS_SNDSTART, ""},
  82.     {"SoundExit", IDS_SNDEXIT, ""},
  83. };
  84.  
  85.  
  86. /* initialised in init.c */
  87. BOOL is_win31 = FALSE;        /* To allow selective use of win 3.1 features */
  88. char szHelpName[MAXSTR];    /* buffer for building help filename */
  89. char szHelpTopic[48];        /* topic for OFN_SHOWHELP */
  90. UINT help_message;        /* message sent by OFN_SHOWHELP */
  91. HMENU hmenu;            /* main menu */
  92. HACCEL haccel;            /* menu accelerators */
  93. HCURSOR hcWait;
  94. POINT img_offset;        /* offset to gswin child window */
  95. POINT info_file;        /* position of file information */
  96. POINT info_page;        /* position of page information */
  97. RECT  info_rect;        /* position and size of brief info area */
  98. RECT  info_coord;        /* position and size of coordinate information */
  99. RECT  button_rect;        /* position and size of button area */
  100.  
  101. BOOL prev_in_child;        /* true if cursor previously in gswin child window */
  102. BOOL waiting = FALSE;        /* true when 'wait' to be displayed in info area */
  103. BOOL page_ready = FALSE;    /* true when gswin has sent an OUTPUT_PAGE and is waiting for NEXT_PAGE */
  104. BOOL saved = FALSE;        /* true if interpreter state currently saved in /gssave */
  105. BOOL epsf_clipped;        /* clipping this page? */
  106. int page_skip = 5;        /* number of pages to skip in IDM_NEXTSKIP or IDM_PREVSKIP */
  107. BOOL debug = FALSE;        /* /D command line option used */
  108. HINSTANCE hlib_mmsystem;    /* DLL containing sndPlaySound function */
  109. FPSPS lpfnSndPlaySound;        /* pointer to sndPlaySound function if loaded */
  110.  
  111. /* timer used for open, close, display & print timeouts */
  112. BOOL bTimeout;            /* true if timeout occured */
  113. BOOL bTimerSet;            /* true if TIMER running */
  114. #define ID_MYTIMER 1
  115. UINT timeout_count;
  116.  
  117. /* document manipulation */
  118. struct document *doc;    /* DSC structure.  NULL if not DSC */
  119. int pagenum;        /* current page number */
  120. char dfname[MAXSTR];    /* name of selected document file */
  121. FILE *dfile;        /* selected file */
  122. char cfname[MAXSTR];    /* temporary command filename */
  123. FILE *cfile;        /* command file */
  124. char efname[MAXSTR];    /* name of temporary file containing PS extracted from DOS EPS file */
  125. char pfname[MAXSTR];    /* name of temporary file for printing options */
  126. BOOL is_ctrld;        /* TRUE if DSC except for ctrl+D at start of file */
  127. int preview;        /* preview type IDS_EPSF, IDS_EPSI, etc. */
  128. struct page_list_s page_list;    /*  page selection for print/extract */
  129.  
  130. /* imitation pipes using SHAREABLE GLOBAL MEMORY */
  131. /* Write gswin commands to temporary file then call pipe_file(tempname) */
  132. /* gswin has finished with file when bPipeDone = TRUE */
  133. BOOL bPipeDone = FALSE;    /* has PIPE_REQUEST been received and not met? */
  134. HFILE hfPipe = NULL;    /* file handle for pipe */
  135.  
  136. /* local functions */
  137. BOOL draw_button(DRAWITEMSTRUCT FAR *lpdis);
  138. BOOL in_child_client_area(void);
  139. BOOL in_client_area(void);
  140. BOOL in_info_area(void);
  141. void info_paint(HWND);
  142. void gsview_close(void);
  143. int gsview_command(WORD);
  144. void dsc_next(int);
  145. void dsc_prev(int);
  146. BOOL not_open(void);
  147. BOOL not_dsc(void);
  148.  
  149. int PASCAL 
  150. WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdLine, int cmdShow)
  151. {
  152.     MSG msg;
  153.  
  154.     /* copy the hInstance into a variable so it can be used */
  155.     phInstance = hInstance;
  156.  
  157.     LoadString(hInstance, IDS_TITLE, szAppName, sizeof(szAppName));
  158.     if (hPrevInstance) {
  159.         /* don't run more than one copy */
  160.         /* because we can't run more than one Ghostscript */
  161.         gsview_init0(lpszCmdLine);
  162.         return FALSE;
  163.     }
  164.  
  165.     gsview_init1(lpszCmdLine);
  166.     ShowWindow(hwndimg, cmdShow);
  167.     
  168.     while (GetMessage(&msg, (HWND)NULL, 0, 0)) {
  169.         if ((hDlgModeless == 0) || !IsDialogMessage(hDlgModeless, &msg)) {
  170.             if (!TranslateAccelerator(hwndimg, haccel, &msg)) {
  171.             TranslateMessage(&msg);
  172.             DispatchMessage(&msg);
  173.             }
  174.         }
  175.     }
  176.  
  177.     play_sound(SOUND_EXIT);
  178.     gsview_close();
  179.     gswin_close();
  180.      WinHelp(hwndimg,szHelpName,HELP_QUIT,(DWORD)NULL);
  181.     if (is_win31 && (hlib_mmsystem != (HINSTANCE)NULL))
  182.         FreeLibrary(hlib_mmsystem);
  183.     return 0;
  184. }
  185.  
  186.  
  187. /* parent overlapped window */
  188. LRESULT CALLBACK _export
  189. WndImgProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
  190. {
  191. RECT rect;
  192.  
  193.     if (message == WM_GSVIEW) {
  194.     switch(wParam) {
  195.         case HWND_TEXT:
  196.         /* lParam = handle to Ghostscript Borland EasyWin window */
  197.         hwndtext = (HWND)lParam;
  198.         break;
  199.         case HWND_IMGCHILD:
  200.         /* lParam = handle to Ghostscript image child window */
  201.         hwndimgchild = (HWND)lParam;
  202.         if (hwndimgchild && IsWindow(hwndimgchild)) {
  203.             SetClassCursor(hwndimgchild, LoadCursor((HINSTANCE)NULL, IDC_CROSS));
  204.             GetClientRect(hwnd, &rect);
  205.             SetWindowPos(hwndimgchild, (HWND)NULL, rect.left+img_offset.x, rect.top+img_offset.y,
  206.             rect.right-img_offset.x, rect.bottom-img_offset.y, 
  207.             SWP_NOZORDER | SWP_NOACTIVATE);
  208.         }
  209.         break;
  210.         case GSWIN_CLOSE:
  211.         /* something is closing gswin */
  212.         gswin_hinst = (HINSTANCE)NULL;
  213.         hwndimgchild = (HWND)NULL;
  214.         hwndtext = (HWND)NULL;
  215.         bitmap_scrollx = bitmap_scrolly = 0;
  216.         page_ready = FALSE;
  217.         saved = FALSE;
  218.         pipe_clean();
  219.         clear_timer();
  220.         info_wait(FALSE);
  221.         break;
  222.         case OUTPUT_PAGE:
  223.         /* showpage has just been called */
  224.         clear_timer();
  225.         play_sound(SOUND_PAGE);
  226.         if (IsIconic(hwndimg))    /* useless as an Icon so fix it */
  227.             ShowWindow(hwndimg, SW_SHOWNORMAL);
  228.         if ( !IsIconic(hwndimg) ) {  /* redraw child window */
  229.             if (hwndimgchild && IsWindow(hwndimgchild)) {
  230.             /* don't erase background - the bitmap will cover it anyway */
  231.             InvalidateRect(hwndimgchild, (LPRECT)NULL, FALSE);
  232.             UpdateWindow(hwndimgchild);
  233.             }
  234.         }
  235.         page_ready = TRUE;
  236.         info_wait(FALSE);
  237.         break;
  238.         case SYNC_OUTPUT:
  239.         /* time to redraw window */
  240.         if ( !IsIconic(hwndimg) ) {  /* redraw child window */
  241.             if (hwndimgchild && IsWindow(hwndimgchild)) {
  242.             /* don't erase background - the bitmap will cover it anyway */
  243.             InvalidateRect(hwndimgchild, (LPRECT)NULL, FALSE);
  244.             UpdateWindow(hwndimgchild);
  245.             }
  246.         }
  247.         break;
  248.         case SCROLL_POSITION:
  249.         /* User scrolled image window.  
  250.          * lParam = offsets to top left of image window
  251.          * we use these to display coordinates */
  252.         bitmap_scrollx = LOWORD(lParam);
  253.         bitmap_scrolly = HIWORD(lParam);
  254.         InvalidateRect(hwndimg, &info_coord, FALSE);
  255.         UpdateWindow(hwndimg);
  256.         break;
  257.         case PIPE_REQUEST:
  258.         if (hfPipe) {
  259.             if (pipe_blk(hfPipe) <= 0)
  260.             pipe_clean();
  261.             }
  262.         else
  263.             pipe_clean();
  264.         break;
  265.         default:
  266.         gserror(0, "Unknown Message", MB_ICONEXCLAMATION, -1);
  267.     }
  268.     return 0;
  269.     }
  270.     else if (message == help_message) {
  271.     WinHelp(hwndimg,szHelpName,HELP_KEY,(DWORD)szHelpTopic);
  272.     return 0;
  273.     } else
  274.     switch(message) {
  275.     case WM_CREATE:
  276.         hwndimg = hwnd;
  277.         gsview_create();
  278.         /* Enable Drag Drop */
  279.         if (is_win31)
  280.             DragAcceptFiles(hwnd, TRUE);
  281.         break;
  282.     case WM_DESTROY:
  283.         /* disable Drag Drop */
  284.         if (is_win31)
  285.             DragAcceptFiles(hwnd, FALSE);
  286.         gsview_close();
  287.         PostQuitMessage(0);
  288.         break;
  289.     case WM_ENDSESSION:
  290.         if (wParam)
  291.             gsview_close();
  292.         return 0;
  293.     case WM_TIMER:
  294.         if (wParam == ID_MYTIMER) {
  295.             timeout_count--;
  296.             if (timeout_count <= 0) {
  297.             clear_timer();
  298.             bTimeout = TRUE;
  299.             gserror(IDS_TIMEOUT, NULL, MB_ICONINFORMATION, SOUND_TIMEOUT);
  300.             info_wait(FALSE);
  301.             }
  302.         }
  303.         break;
  304.     case WM_DROPFILES:
  305.         if (is_win31) {
  306.             LPSTR szFile;
  307.             int i, cFiles, length;
  308.             HDROP hdrop = (HDROP)wParam;
  309.             cFiles = DragQueryFile(hdrop, 0xffff, (LPSTR)NULL, 0);
  310.             for (i=0; i<cFiles; i++) {
  311.             length = DragQueryFile(hdrop, i, (LPSTR)NULL, 0);
  312.             szFile = GlobalAllocPtr(GHND, length+1);
  313.             if (szFile) {
  314.                 DragQueryFile(hdrop, i, szFile, MAXSTR);
  315.                 /* it doesn't work if we call gsview_display directly */
  316.                 PostMessage(hwnd, WM_COMMAND, IDM_DROP, (LPARAM)szFile);
  317.             }
  318.             }
  319.             DragFinish(hdrop);
  320.         }
  321.         break;
  322.     case WM_INITMENU:
  323.         if (hmenu == (HMENU)wParam) {
  324.             HMENU hmenuedit = GetSubMenu(hmenu,1);
  325.             if (hwndimgchild  && IsWindow(hwndimgchild))
  326.             EnableMenuItem(hmenu, IDM_COPYCLIP, MF_ENABLED);
  327.             else
  328.             EnableMenuItem(hmenu, IDM_COPYCLIP, MF_DISABLED | MF_GRAYED);
  329.             if (OpenClipboard(hwnd)) {
  330.             if (IsClipboardFormatAvailable(CF_DIB))
  331.                 EnableMenuItem(hmenu, IDM_PASTETO, MF_ENABLED);
  332.             else
  333.                 EnableMenuItem(hmenu, IDM_PASTETO, MF_DISABLED | MF_GRAYED);
  334.             if (IsClipboardFormatAvailable(CF_DIB) || 
  335.                 IsClipboardFormatAvailable(CF_BITMAP)) 
  336.                 EnableMenuItem(hmenu, IDM_CONVERT, MF_ENABLED);
  337.             else
  338.                 EnableMenuItem(hmenu, IDM_CONVERT, MF_DISABLED | MF_GRAYED);
  339.             /* Make EPS sub menu */
  340.             if ((IsClipboardFormatAvailable(CF_DIB) ||
  341.                  IsClipboardFormatAvailable(CF_BITMAP)) 
  342.                 && (doc != (struct document *)NULL) && doc->epsf)
  343.                 EnableMenuItem(hmenuedit, 5, MF_BYPOSITION | MF_ENABLED);
  344.             else
  345.                 EnableMenuItem(hmenuedit, 5, MF_BYPOSITION | MF_DISABLED | MF_GRAYED);
  346.             /* Extract EPS sub menu */
  347.             if ( (preview == IDS_EPST) || (preview == IDS_EPSW) )
  348.                 EnableMenuItem(hmenuedit, 6, MF_BYPOSITION | MF_ENABLED);
  349.             else
  350.                 EnableMenuItem(hmenuedit, 6, MF_BYPOSITION | MF_DISABLED | MF_GRAYED);
  351.             CloseClipboard();
  352.             }
  353.             return 0;
  354.         }
  355.         break;
  356.     case WM_COMMAND:
  357.         if (LOWORD(wParam) == IDM_DROP) {
  358.             HGLOBAL hglobal;
  359.             char buf[MAXSTR];
  360.             if (lstrlen((LPSTR)lParam) < sizeof(buf))
  361.             lstrcpy(buf, (LPSTR)lParam);
  362.             else
  363.             buf[0] = '\0';
  364.             hglobal = (HGLOBAL)LOWORD(GlobalHandle(SELECTOROF(lParam)));
  365.             GlobalUnlock(hglobal);
  366.             GlobalFree(hglobal);
  367.             if (strnicmp(buf,"/P ",3)==0) {
  368.                 gsview_selectfile(buf+3);
  369.                 gsview_print(FALSE);
  370.             }
  371.             else if (strnicmp(buf,"/F ",3)==0) {
  372.                 gsview_selectfile(buf+3);
  373.                 gsview_print(TRUE);
  374.             }
  375.             else
  376.                 gsview_displayfile(buf);
  377.         }
  378.         else
  379.              gsview_command(LOWORD(wParam));
  380.         return 0;
  381.     case WM_KEYDOWN:
  382.     case WM_KEYUP:
  383.         /* pass on key presses so that child window scroll bars work */
  384.         if (hwndimgchild && IsWindow(hwndimgchild)) {
  385.             SendMessage(hwndimgchild, message, wParam, lParam);
  386.             return 0;
  387.         }
  388.         break;
  389.     case WM_SIZE:
  390.         /* make child window fill client area */
  391.         if (wParam != SIZE_MINIMIZED  && hwndimgchild !=(HWND)NULL && IsWindow(hwndimgchild))
  392.             SetWindowPos(hwndimgchild, (HWND)NULL, img_offset.x, img_offset.y,
  393.             LOWORD(lParam)-img_offset.x, HIWORD(lParam)-img_offset.y, 
  394.             SWP_NOZORDER | SWP_NOACTIVATE);
  395.         /* save window size for INIFILE */
  396.         if (wParam == SIZE_RESTORED) {
  397.             GetWindowRect(hwnd,&rect);
  398.             img_size.x = rect.right-rect.left;
  399.             img_size.y = rect.bottom-rect.top;
  400.         }
  401.         return 0;
  402.     case WM_MOVE:
  403.         /* save window position for INIFILE */
  404.         if (!IsIconic(hwnd) && !IsZoomed(hwnd)) {
  405.             GetWindowRect(hwnd,&rect);
  406.             img_origin.x = rect.left;
  407.             img_origin.y = rect.top;
  408.         }
  409.         return 0;
  410.     case WM_SETCURSOR:
  411.         /* if waiting, display hourglass cursor over our window */
  412.         if (waiting) {
  413.             if (hwndimgchild && IsWindow(hwndimgchild)) {
  414.             if (in_child_client_area() || in_info_area() || (LOWORD(lParam)==HTMENU)) {
  415.                 SetCursor(hcWait);
  416.                 return TRUE;
  417.                 }
  418.             }
  419.             else {
  420.                 SetCursor(hcWait);
  421.                 return TRUE;
  422.             }
  423.         }
  424.         /* track cursor and display coordinates if in child window */
  425.         if (hwndimgchild && IsWindow(hwndimgchild)) {
  426.             if (in_child_client_area() || prev_in_child) {
  427.             /* update coordinate info */
  428.             InvalidateRect(hwndimg, &info_coord, FALSE);
  429.             UpdateWindow(hwndimg);
  430.             }
  431.             prev_in_child = in_child_client_area();
  432.         }
  433.         break;
  434.     case WM_PARENTNOTIFY:
  435.         if (hDlgModeless && (wParam == WM_LBUTTONDOWN))
  436.             if (in_child_client_area())
  437.                 SendMessage(hDlgModeless, WM_COMMAND, BB_CLICK, lParam);
  438.         break;
  439.     case WM_PAINT:
  440.         info_paint(hwnd);
  441.         return 0;
  442.     case WM_MEASUREITEM:
  443.         return 1;
  444.     case WM_DRAWITEM:
  445.         return draw_button((DRAWITEMSTRUCT FAR *)lParam);
  446.     }
  447.     return DefWindowProc(hwnd, message, wParam, lParam);
  448. }
  449.  
  450. /* return TRUE if button drawn */
  451. BOOL
  452. draw_button(DRAWITEMSTRUCT FAR *lpdis)
  453. {
  454. HBRUSH hbrush;
  455. HPEN hpen_highlight, hpen_shadow, hpen_old;
  456. HDC hdc = lpdis->hDC;
  457. RECT rect;
  458. HICON hicon;
  459. HBITMAP hbitmap_old, hbitmap;
  460. BITMAP bm;
  461. int i;
  462. char buf[20];
  463.     rect = lpdis->rcItem;
  464.     if (lpdis->CtlType != ODT_BUTTON)
  465.         return FALSE;
  466.     switch (lpdis->itemAction) {
  467.         case ODA_DRAWENTIRE:
  468.         if ((hbitmap = LoadBitmap(phInstance,MAKEINTRESOURCE(lpdis->CtlID)))
  469.           != (HBITMAP)NULL) {
  470.             HDC hdcsrc = CreateCompatibleDC(hdc);
  471.             hbitmap_old = SelectObject(hdcsrc,hbitmap);
  472.             GetObject(hbitmap, sizeof(BITMAP),&bm);
  473.             if ( (rect.right-rect.left > bm.bmWidth) ||
  474.              (rect.bottom-rect.top > bm.bmHeight) ) {
  475.                 hbrush = CreateSolidBrush(GetSysColor(COLOR_BTNFACE));
  476.                 FillRect(hdc, &rect, hbrush);
  477.                 DeleteBrush(hbrush);
  478.             }
  479.             BitBlt(hdc, (rect.left+rect.right-bm.bmWidth)/2,
  480.                (rect.top+rect.bottom-bm.bmHeight)/2,
  481.                bm.bmWidth,bm.bmHeight,hdcsrc,0,0,SRCCOPY);
  482.             SelectObject(hdcsrc,hbitmap_old);
  483.             DeleteObject(hbitmap);
  484.             DeleteDC(hdcsrc);
  485.         }
  486.         else {
  487.             hbrush = CreateSolidBrush(GetSysColor(COLOR_BTNFACE));
  488.             FillRect(hdc, &rect, hbrush);
  489.             DeleteBrush(hbrush);
  490.             if ((i = LoadString(phInstance, lpdis->CtlID, buf, sizeof(buf)))
  491.                 != 0) {
  492.             DWORD dw = GetTextExtent(hdc, buf, i);
  493.             SetBkMode(hdc, TRANSPARENT);
  494.             TextOut(hdc, (rect.left+rect.right-LOWORD(dw))/2,
  495.                 (rect.top+rect.bottom-HIWORD(dw))/2, buf, i);
  496.             }
  497.             else if ( (hicon = LoadIcon(phInstance, MAKEINTRESOURCE(lpdis->CtlID)))
  498.                 != (HICON)NULL )  {
  499.                 DrawIcon(hdc, (rect.left+rect.right-32)/2, 
  500.                     (rect.top+rect.bottom-32)/2, hicon);
  501.                 DestroyIcon(hicon);
  502.             }
  503.         }
  504.         hpen_old = SelectPen(hdc, GetStockObject(BLACK_PEN));
  505.         MoveTo(hdc, rect.left, rect.top);
  506.         LineTo(hdc, rect.right-1, rect.top);
  507.         LineTo(hdc, rect.right-1, rect.bottom-1);
  508.         LineTo(hdc, rect.left, rect.bottom-1);
  509.         LineTo(hdc, rect.left, rect.top-1);
  510.         SelectPen(hdc, hpen_old);
  511.         /* fall thru */
  512.         case ODA_FOCUS:
  513.         case ODA_SELECT:
  514.         if (lpdis->itemState & ODS_SELECTED) {
  515.             hpen_highlight = CreatePen(PS_SOLID, 1, GetSysColor(COLOR_BTNSHADOW));
  516.             hpen_shadow = CreatePen(PS_SOLID, 1, GetSysColor(COLOR_BTNFACE));
  517.         }
  518.         else {
  519.             hpen_highlight = CreatePen(PS_SOLID, 1, is_win31 ? GetSysColor(COLOR_BTNHIGHLIGHT) : RGB(255,255,255));
  520.             hpen_shadow = CreatePen(PS_SOLID, 1, GetSysColor(COLOR_BTNSHADOW));
  521.         }
  522.         hpen_old = SelectPen(hdc, hpen_highlight);
  523.         MoveTo(hdc, rect.left+1, rect.bottom-3);
  524.         LineTo(hdc, rect.left+1, rect.top+1);
  525.         LineTo(hdc, rect.right-2, rect.top+1);
  526.         MoveTo(hdc, rect.right-3, rect.top+2);
  527.         LineTo(hdc, rect.left+2, rect.top+2);
  528.         LineTo(hdc, rect.left+2, rect.bottom-4);
  529.         SelectPen(hdc, hpen_shadow);
  530.         MoveTo(hdc, rect.left+1, rect.bottom-2);
  531.         LineTo(hdc, rect.right-2, rect.bottom-2);
  532.         LineTo(hdc, rect.right-2, rect.top+1);
  533.         MoveTo(hdc, rect.right-3, rect.top+2);
  534.         LineTo(hdc, rect.right-3, rect.bottom-3);
  535.         LineTo(hdc, rect.left+2, rect.bottom-3);
  536.         SelectPen(hdc, hpen_old);
  537.         DeleteObject(hpen_highlight);
  538.         DeleteObject(hpen_shadow);
  539.             return TRUE;
  540.     }
  541.     return FALSE;
  542. }
  543.  
  544. /* returns true if cursor in client area of Ghostscript image window */
  545. BOOL
  546. in_child_client_area()
  547. {
  548. RECT rect;
  549. POINT pt;
  550. HWND hwnd;
  551.         GetCursorPos(&pt);
  552.     hwnd = WindowFromPoint(pt);
  553.     if ((hwnd != hwndimg) && !IsChild(hwndimg,hwnd))
  554.         return 0;
  555.         GetClientRect(hwndimgchild, &rect);
  556.         ScreenToClient(hwndimgchild, &pt);
  557.         return PtInRect(&rect, pt);
  558. }
  559.  
  560. /* returns true if cursor in client area of Ghostview window */
  561. BOOL
  562. in_client_area()
  563. {
  564. RECT rect;
  565. POINT pt;
  566. HWND hwnd;
  567.         GetCursorPos(&pt);
  568.     hwnd = WindowFromPoint(pt);
  569.     if ((hwnd != hwndimg) && !IsChild(hwndimg,hwnd))
  570.         return 0;
  571.         GetClientRect(hwndimg, &rect);
  572.         ScreenToClient(hwndimg, &pt);
  573.         return PtInRect(&rect, pt);
  574. }
  575.  
  576. /* returns true if cursor in info area or button area of Ghostview windows */
  577. BOOL
  578. in_info_area()
  579. {
  580. RECT rect;
  581. POINT pt;
  582. HWND hwnd;
  583.         GetCursorPos(&pt);
  584.     hwnd = WindowFromPoint(pt);
  585.     if ((hwnd != hwndimg) && !IsChild(hwndimg,hwnd))
  586.         return 0;
  587.         ScreenToClient(hwndimg, &pt);
  588.  
  589.         GetClientRect(hwndimg, &rect);
  590.     rect.bottom = img_offset.y;
  591.     if (PtInRect(&rect, pt))
  592.         return TRUE;
  593.         GetClientRect(hwndimg, &rect);
  594.     rect.right = img_offset.x;
  595.         return PtInRect(&rect, pt);
  596. }
  597.  
  598. BOOL
  599. get_cursorpos(int *x, int *y)
  600. {
  601. RECT rect;
  602. POINT pt;
  603.     if (hwndimgchild && IsWindow(hwndimgchild)) {
  604.     GetClientRect(hwndimgchild, &rect);
  605.     GetCursorPos(&pt);
  606.     ScreenToClient(hwndimgchild, &pt);
  607.     if (PtInRect(&rect, pt)) {
  608.         *x = (int)((bitmap_scrollx+pt.x)*72.0/xdpi 
  609.         + (epsf_clipped ? doc->boundingbox[LLX] : 0));
  610.         *y = (int)(((bitmap_height-1)-(bitmap_scrolly+pt.y))*72.0/ydpi
  611.         + (epsf_clipped ? doc->boundingbox[LLY] : 0));
  612.         return TRUE;
  613.     }
  614.     }
  615.     return FALSE;
  616. }
  617.  
  618. /* paint brief info area */
  619. void
  620. info_paint(HWND hwnd)
  621. {
  622. HDC hdc;
  623. PAINTSTRUCT ps;
  624. RECT rect;
  625. int i;
  626. char buf[MAXSTR];
  627. char fmt[MAXSTR];
  628. int x, y;
  629.     hdc = BeginPaint(hwnd, &ps);
  630.     SetBkMode(hdc, TRANSPARENT);
  631.     if (info_rect.bottom) {
  632.         GetClientRect(hwnd, &rect);
  633.         rect.top = 0;
  634.         rect.left = info_rect.left;
  635.         rect.bottom = info_rect.bottom;
  636.         FillRect(hdc, &rect, GetStockObject(LTGRAY_BRUSH));
  637.         SelectPen(hdc, GetStockObject(BLACK_PEN));
  638.         MoveTo(hdc, rect.left, rect.bottom);
  639.         LineTo(hdc, rect.right, rect.bottom);
  640.     }
  641.     if (button_rect.right) {
  642.         GetClientRect(hwnd, &rect);
  643.         rect.top = button_rect.top;
  644.         rect.left = button_rect.left;
  645.         rect.right = button_rect.right;
  646.         FillRect(hdc, &rect, GetStockObject(LTGRAY_BRUSH));
  647.         SelectPen(hdc, GetStockObject(BLACK_PEN));
  648.         MoveTo(hdc, rect.right, rect.top);
  649.         LineTo(hdc, rect.right, rect.bottom);
  650.     }
  651.     /* write file information */
  652.     if (dfname[0] != '\0') {
  653.         i = LoadString(phInstance, IDS_FILE, buf, sizeof(buf));
  654.         GetFileTitle(dfname, buf+i, sizeof(buf)-i);
  655.         TextOut(hdc, info_file.x, info_file.y, buf, strlen(buf));
  656.         if (waiting) {
  657.         i = LoadString(phInstance, IDS_WAIT, buf, sizeof(buf));
  658.         TextOut(hdc, info_page.x, info_page.y, buf, strlen(buf));
  659.         }
  660.         else {
  661.           if (doc!=(struct document *)NULL) {
  662.         int n = map_page(pagenum - 1);
  663.         i = LoadString(phInstance, IDS_PAGEINFO, fmt, sizeof(fmt));
  664.         if (doc->pages)
  665.             sprintf(buf, fmt, doc->pages[n].label ? doc->pages[n].label : " ",pagenum,  doc->numpages);
  666.         else
  667.             sprintf(buf, fmt, " " ,pagenum,  doc->numpages);
  668.         TextOut(hdc, info_page.x, info_page.y, buf, strlen(buf));
  669.           }
  670.           else {
  671.         if (bPipeDone)
  672.             i = LoadString(phInstance, IDS_NOMORE, buf, sizeof(buf));
  673.         else {
  674.             i = LoadString(phInstance, IDS_PAGE, buf, sizeof(buf));
  675.             sprintf(buf+i, "%d", pagenum);
  676.         }
  677.         TextOut(hdc, info_page.x, info_page.y, buf, strlen(buf));
  678.           }
  679.           /* show coordinate */
  680.           if (get_cursorpos(&x, &y)) {
  681.             sprintf(buf,"%d, %d", x, y);
  682.             SetTextAlign(hdc, TA_RIGHT);
  683.             TextOut(hdc, info_coord.right-1, info_coord.top, buf, strlen(buf));
  684.           }
  685.         }
  686.     }
  687.     else {
  688.         i = LoadString(phInstance, IDS_NOFILE, buf, sizeof(buf));
  689.         TextOut(hdc, info_file.x, info_file.y, buf, strlen(buf));
  690.         if (waiting) {
  691.         i = LoadString(phInstance, IDS_WAIT, buf, sizeof(buf));
  692.         TextOut(hdc, info_page.x, info_page.y, buf, strlen(buf));
  693.         }
  694.     }
  695.     EndPaint(hwnd, &ps);
  696. }
  697.  
  698. /* subclass button WndProc to give focus back to parent window */
  699. LRESULT CALLBACK _export
  700. MenuButtonProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
  701. {
  702.     switch(message) {
  703.         case WM_LBUTTONUP:
  704.         {
  705.         RECT rect;
  706.         POINT pt;
  707.         GetWindowRect(hwnd, &rect);
  708.         GetCursorPos(&pt);
  709.         if (PtInRect(&rect, pt))
  710.             SendMessage(GetParent(hwnd), WM_COMMAND, GetWindowID(hwnd), 0L);
  711.         SetFocus(GetParent(hwnd));
  712.         }
  713.         break;
  714.     }
  715.     return CallWindowProc(lpfnButtonWndProc, hwnd, message, wParam, lParam);
  716. }
  717.  
  718.  
  719. void
  720. play_sound(int num)
  721. {
  722.     if (strlen(sound[num].file)==0)
  723.         return;
  724.     if (!is_win31 || (strcmp(sound[num].file,BEEP)==0)) {
  725.         MessageBeep(-1);
  726.         return;
  727.     }
  728.     if (is_win31) {
  729.         if (lpfnSndPlaySound != (FPSPS)NULL) 
  730.                lpfnSndPlaySound(sound[num].file, SND_SYNC);
  731.         else
  732.             MessageBeep(-1);
  733.         return;
  734.     }
  735. }
  736.  
  737. BOOL
  738. set_timer(UINT period)
  739. {
  740.     timeout_count = period;
  741.     bTimeout = FALSE;
  742.     if (SetTimer(hwndimg, ID_MYTIMER, 1000, NULL) != 0) {
  743.         bTimerSet = TRUE;
  744.         return TRUE;
  745.     }
  746.  
  747.     bTimerSet = FALSE;
  748.     gserror(IDS_NOTIMER, NULL, MB_ICONINFORMATION, SOUND_TIMEOUT);
  749.     return FALSE;
  750. }
  751.  
  752. void
  753. clear_timer()
  754. {
  755.     if (bTimerSet)
  756.         KillTimer(hwndimg, ID_MYTIMER);
  757.     bTimerSet = FALSE;
  758.     bTimeout = FALSE;
  759.     EnableWindow(hwndimg, TRUE);
  760. }
  761.  
  762. /* display or remove 'wait' message */
  763. void
  764. info_wait(BOOL wait)
  765. {
  766. HWND hwnd;
  767. POINT pt;
  768.     waiting = wait;
  769.     InvalidateRect(hwndimg, (LPRECT)&info_rect, FALSE);
  770.     UpdateWindow(hwndimg);
  771.  
  772.     if (waiting) {
  773.             GetCursorPos(&pt);
  774.         hwnd = WindowFromPoint(pt);
  775.         if ((hwnd == hwndimg) || IsChild(hwndimg,hwnd))
  776.         SetCursor(hcWait);
  777.     }
  778.     else {
  779.         /* set cursor to that of active window */
  780.         hwnd = GetFocus();
  781.         if ( (hwndimgchild && IsWindow(hwndimgchild))
  782.           && ((hwnd == hwndimg) || (hwnd == hwndimgchild)) ) {
  783.         if (in_child_client_area()) {
  784.             SetCursor(GetClassCursor(hwndimgchild));
  785.             return;
  786.         }
  787.         }
  788.         SetCursor(GetClassCursor(hwnd));
  789.     }
  790. }
  791.  
  792.  
  793. /* remove temporary files */
  794. void
  795. gsview_close()
  796. {
  797.     if ((cfname[0] != '\0') && !debug)
  798.         unlink(cfname);
  799.     cfname[0] = '\0';
  800.     if ((efname[0] != '\0') && !debug)
  801.         unlink(efname);
  802.     efname[0] = '\0';
  803.     if ((pfname[0] != '\0') && !debug)
  804.         unlink(pfname);
  805.     pfname[0] = '\0';
  806.     if (page_list.select)
  807.         free(page_list.select);
  808.     page_list.select = NULL;
  809.     if (doc)
  810.         psfree(doc);
  811.     doc = 0;
  812.     if (settings)
  813.         write_profile();
  814.     return;
  815. }
  816.  
  817.  
  818. /* gsview menu commands */
  819. int
  820. gsview_command(WORD command)
  821. {
  822. char prompt[MAXSTR];        /* input dialog box prompt and message box string */
  823. char answer[MAXSTR];        /* input dialog box answer string */
  824.     if (hDlgModeless) {
  825.     play_sound(SOUND_ERROR);
  826.     return 0;    /* obtaining Bounding Box so ignore commands */
  827.     }
  828.     if (waiting) {
  829.     /* if user impatient or gsview confused */
  830.     LoadString(phInstance, IDS_BUSY, prompt, sizeof(prompt));
  831.     if (MessageBox(hwndimg, prompt, szAppName, MB_YESNO | MB_ICONQUESTION) == IDYES) {
  832.         play_sound(SOUND_ERROR);
  833.         pipe_clean();
  834.         next_page();
  835.         info_wait(FALSE);
  836.     }
  837.     return 0;
  838.     }
  839.     switch (command) {
  840.     case IDM_OPEN:
  841.         gsview_display();
  842.         return 0;
  843.     case IDM_NEXT:
  844.         if (not_open())
  845.             return 0;
  846.         if (gswin_open())
  847.             return 0;
  848.         info_wait(TRUE);
  849.         if (doc==(struct document *)NULL) {
  850.             if (bPipeDone) {
  851.             play_sound(SOUND_NOPAGE);
  852.             info_wait(FALSE);
  853.             }
  854.             else {
  855.             pagenum++;
  856.             next_page();
  857.             }
  858.             return 0;
  859.         }
  860.         dsc_next(1);
  861.         return 0;
  862.     case IDM_NEXTSKIP:
  863.         if (not_open())
  864.             return 0;
  865.         if (not_dsc())
  866.             return 0;
  867.         dsc_next(page_skip);
  868.         return 0;
  869.     case IDM_REDISPLAY:
  870.         if (not_open())
  871.             return 0;
  872.         info_wait(TRUE);
  873.         if (doc==(struct document *)NULL) {
  874.             /* don't know where we are so close and reopen */
  875.             if (!bPipeDone)
  876.             gswin_close();
  877.         }
  878.         if (gswin_open())
  879.             return 0;
  880.         info_wait(TRUE);
  881.         if (page_ready)
  882.             next_page(); 
  883.         if ((doc==(struct document *)NULL) || (doc->pages==0)) {
  884.             gsview_displayfile(dfname);
  885.             return 0;
  886.         }
  887.         dsc_dopage();
  888.         return 0;
  889.     case IDM_PREV:
  890.         if (not_open())
  891.             return 0;
  892.         if (not_dsc())
  893.             return 0;
  894.         dsc_prev(1);
  895.         return 0;
  896.     case IDM_PREVSKIP:
  897.         if (not_open())
  898.             return 0;
  899.         if (not_dsc())
  900.             return 0;
  901.         dsc_prev(page_skip);
  902.         return 0;
  903.     case IDM_GOTO:
  904.         if (not_open())
  905.             return 0;
  906.         if (doc!=(struct document *)NULL) {
  907.             if (doc->numpages == 0) {
  908.             gserror(IDS_NOPAGE, NULL, MB_ICONEXCLAMATION, SOUND_NONUMBER);
  909.             return 0;
  910.             }
  911.             if (get_page(&pagenum, FALSE)) {
  912.             if (pagenum > doc->numpages) {
  913.                 pagenum = doc->numpages;
  914.                 play_sound(SOUND_NOPAGE);
  915.                 return 0;
  916.             }
  917.             if (pagenum < 1) {
  918.                 pagenum = 1;
  919.                 play_sound(SOUND_NOPAGE);
  920.                 return 0;
  921.             }
  922.             if (gswin_open())
  923.                 return 0;
  924.             info_wait(TRUE);
  925.             if (page_ready)
  926.                 next_page();
  927.             dsc_dopage();
  928.             }
  929.         }
  930.         else {
  931.             gserror(IDS_NOPAGE, NULL, MB_ICONEXCLAMATION, SOUND_NONUMBER);
  932.         }
  933.         return 0;
  934.     case IDM_INFO:
  935.         {
  936.         DLGPROC lpProcInfo;
  937.         lpProcInfo = (DLGPROC)MakeProcInstance((FARPROC)InfoDlgProc, phInstance);
  938.         DialogBoxParam( phInstance, "InfoDlgBox", hwndimg, lpProcInfo, (LPARAM)NULL);
  939.         FreeProcInstance((FARPROC)lpProcInfo);
  940.         }
  941.         return 0;
  942.     case IDM_SELECT:
  943.         gsview_select();
  944.         return 0;
  945.     case IDM_PRINT:
  946.         if (dfname[0] == '\0')
  947.             gsview_select();
  948.         if (dfname[0] != '\0')
  949.             gsview_print(FALSE);
  950.         return 0;
  951.     case IDM_PRINTTOFILE:
  952.         if (dfname[0] == '\0')
  953.             gsview_select();
  954.         if (dfname[0] != '\0')
  955.             gsview_print(TRUE);
  956.         return 0;
  957.     case IDM_SPOOL:
  958.         gsview_spool();
  959.         return 0;
  960.     case IDM_EXTRACT:
  961.         if (dfname[0] == '\0')
  962.             gsview_select();
  963.         if (dfname[0] != '\0')
  964.             gsview_extract();
  965.         return 0;
  966.     case IDM_EXIT:
  967.         PostQuitMessage(0);
  968.         return 0;
  969.     case IDM_COPYCLIP:
  970.         if (hwndimgchild && IsWindow(hwndimgchild))
  971.             SendMessage(hwndimgchild, WM_GSVIEW, COPY_CLIPBOARD, NULL);
  972.         return 0;
  973.     case IDM_PASTETO:
  974.         clip_to_file();
  975.         return 0;
  976.     case IDM_CONVERT:
  977.         clip_convert();
  978.         return 0;
  979.     case IDM_GSCOMMAND:
  980.         LoadString(phInstance, IDS_GSCOMMAND, prompt, sizeof(prompt));
  981.         strcpy(answer, szGSwin);
  982.         LoadString(phInstance, IDS_TOPICGSCMD, szHelpTopic, sizeof(szHelpTopic));
  983.         if (get_string(prompt,answer))
  984.             strcpy(szGSwin, answer);
  985.         if (szGSwin[0]=='\0')
  986.             strcpy(szGSwin, DEFAULT_GSCOMMAND);
  987.         return 0;
  988.     case IDM_SAVEDIR:
  989.         save_dir = !save_dir;
  990.         CheckMenuItem(hmenu, IDM_SAVEDIR, MF_BYCOMMAND | 
  991.             (save_dir ? MF_CHECKED : MF_UNCHECKED));
  992.         return 0;
  993.     case IDM_BUTTONSHOW:
  994.         button_show = !button_show;
  995.         CheckMenuItem(hmenu, IDM_BUTTONSHOW, MF_BYCOMMAND | 
  996.             (button_show ? MF_CHECKED : MF_UNCHECKED));
  997.         show_buttons();
  998.         return 0;
  999.     case IDM_QUICK:
  1000.         quick = !quick;
  1001.         CheckMenuItem(hmenu, IDM_QUICK, MF_BYCOMMAND | 
  1002.             (quick ? MF_CHECKED : MF_UNCHECKED));
  1003.         return 0;
  1004.     case IDM_AUTOREDISPLAY:
  1005.         redisplay = !redisplay;
  1006.         CheckMenuItem(hmenu, IDM_AUTOREDISPLAY, MF_BYCOMMAND | 
  1007.             (redisplay ? MF_CHECKED : MF_UNCHECKED));
  1008.         return 0;
  1009.     case IDM_EPSFCLIP:
  1010.         epsf_clip = !epsf_clip;
  1011.         CheckMenuItem(hmenu, IDM_EPSFCLIP, MF_BYCOMMAND | 
  1012.             (epsf_clip ? MF_CHECKED : MF_UNCHECKED));
  1013.         gswin_resize();
  1014.         return 0;
  1015.     case IDM_EPSFWARN:
  1016.         epsf_warn = !epsf_warn;
  1017.         CheckMenuItem(hmenu, IDM_EPSFWARN, MF_BYCOMMAND | 
  1018.             (epsf_warn ? MF_CHECKED : MF_UNCHECKED));
  1019.         return 0;
  1020.     case IDM_PSTOEPS:
  1021.         if (dfname[0] == '\0')
  1022.             gsview_display();
  1023.         if (dfname[0] != '\0')
  1024.             ps_to_eps();
  1025.         return 0;
  1026.     case IDM_MAKEEPSI:
  1027.         make_eps_interchange();
  1028.         return 0;
  1029.     case IDM_MAKEEPST:
  1030.         make_eps_tiff();
  1031.         return 0;
  1032.     case IDM_MAKEEPSW:
  1033.         make_eps_metafile();
  1034.         return 0;
  1035.     case IDM_EXTRACTPS:
  1036.     case IDM_EXTRACTPRE:
  1037.         extract_doseps(command);
  1038.         return 0;
  1039.     case IDM_SETTINGS:
  1040.         write_profile();
  1041.         return 0;
  1042.     case IDM_SAVESETTINGS:
  1043.         if (settings) 
  1044.             CheckMenuItem(hmenu, IDM_SAVESETTINGS, MF_BYCOMMAND | MF_UNCHECKED);
  1045.         else
  1046.             CheckMenuItem(hmenu, IDM_SAVESETTINGS, MF_BYCOMMAND | MF_CHECKED);
  1047.         settings = !settings;
  1048.         sprintf(prompt, "%d", settings);
  1049.         WritePrivateProfileString(INISECTION, "SaveSettings", prompt, INIFILE);
  1050.         return 0;
  1051.     case IDM_SOUNDS:
  1052.         {
  1053.         DLGPROC lpProcSound;
  1054.         LoadString(phInstance, IDS_TOPICSOUND, szHelpTopic, sizeof(szHelpTopic));
  1055.         lpProcSound = (DLGPROC)MakeProcInstance((FARPROC)SoundDlgProc, phInstance);
  1056.         DialogBoxParam( phInstance, "SoundDlgBox", hwndimg, lpProcSound, (LPARAM)NULL);
  1057.         FreeProcInstance((FARPROC)lpProcSound);
  1058.         }
  1059.         return 0;
  1060.     case IDM_PORTRAIT:
  1061.     case IDM_LANDSCAPE:
  1062.     case IDM_UPSIDEDOWN:
  1063.     case IDM_SEASCAPE:
  1064.     case IDM_SWAPLANDSCAPE:
  1065.         gsview_orientation(command);
  1066.         return 0;
  1067.     case IDM_RESOLUTION:
  1068.         LoadString(phInstance, IDS_RES, prompt, sizeof(prompt));
  1069.         if (xdpi == ydpi)
  1070.             sprintf(answer,"%g", xdpi);
  1071.         else 
  1072.             sprintf(answer,"%g %g", xdpi, ydpi);
  1073.         LoadString(phInstance, IDS_TOPICMEDIA, szHelpTopic, sizeof(szHelpTopic));
  1074.         if (get_string(prompt,answer)) {
  1075.             switch (sscanf(answer,"%f %f", &xdpi, &ydpi)) {
  1076.               case EOF:
  1077.               case 0:
  1078.             return 0;
  1079.               case 1:
  1080.             ydpi = xdpi;
  1081.               case 2:
  1082.             if (xdpi==0.0)
  1083.                 xdpi = DEFAULT_RESOLUTION;
  1084.             if (ydpi==0.0)
  1085.                 ydpi = DEFAULT_RESOLUTION;
  1086.             gswin_resize();
  1087.             }
  1088.         }
  1089.         return 0;
  1090.     case IDM_LETTER:
  1091.     case IDM_LETTERSMALL:
  1092.     case IDM_TABLOID:
  1093.     case IDM_LEDGER:
  1094.     case IDM_LEGAL:
  1095.     case IDM_STATEMENT:
  1096.     case IDM_EXECUTIVE:
  1097.     case IDM_A3:
  1098.     case IDM_A4:
  1099.     case IDM_A4SMALL:
  1100.     case IDM_A5:
  1101.     case IDM_B4:
  1102.     case IDM_B5:
  1103.     case IDM_FOLIO:
  1104.     case IDM_QUARTO:
  1105.     case IDM_10X14:
  1106.     case IDM_USERSIZE:
  1107.         if (command == IDM_USERSIZE)
  1108.             if (!gsview_usersize())
  1109.             return 0;
  1110.         gsview_media(command);
  1111.         return 0;
  1112.     case IDM_HELPCONTENT:
  1113.         WinHelp(hwndimg,szHelpName,HELP_CONTENTS,(DWORD)NULL);
  1114.         return 0;
  1115.     case IDM_HELPSEARCH:
  1116.         WinHelp(hwndimg,szHelpName,HELP_PARTIALKEY,(DWORD)"");
  1117.         return 0;
  1118.     case IDM_ABOUT:
  1119.         {
  1120.         DLGPROC lpProcAbout;
  1121.         lpProcAbout = (DLGPROC)MakeProcInstance((FARPROC)AboutDlgProc, phInstance);
  1122.         DialogBoxParam( phInstance, "AboutDlgBox", hwndimg, lpProcAbout, (LPARAM)NULL);
  1123.         FreeProcInstance((FARPROC)lpProcAbout);
  1124.         }
  1125.         return 0;
  1126.     }
  1127.     return 0;
  1128. }
  1129.  
  1130. void
  1131. gsview_orientation(int new_orientation)
  1132. {
  1133.     if (new_orientation == orientation)
  1134.         return;
  1135.     if (new_orientation == IDM_SWAPLANDSCAPE) {
  1136.         swap_landscape = !swap_landscape;
  1137.         if (swap_landscape) 
  1138.             CheckMenuItem(hmenu, IDM_SWAPLANDSCAPE, MF_BYCOMMAND | MF_CHECKED);
  1139.         else
  1140.             CheckMenuItem(hmenu, IDM_SWAPLANDSCAPE, MF_BYCOMMAND | MF_UNCHECKED);
  1141.         if ((orientation != IDM_LANDSCAPE) && (orientation != IDM_SEASCAPE))
  1142.             return;
  1143.     }
  1144.     else {
  1145.         CheckMenuItem(hmenu, orientation, MF_BYCOMMAND | MF_UNCHECKED);
  1146.         orientation = new_orientation;
  1147.         CheckMenuItem(hmenu, orientation, MF_BYCOMMAND | MF_CHECKED);
  1148.     }
  1149.     gswin_resize();
  1150.     return;
  1151. }
  1152.  
  1153. void
  1154. gsview_media(int new_media)
  1155. {
  1156.     if ( (new_media == media) && (new_media != IDM_USERSIZE) )
  1157.         return;
  1158.     CheckMenuItem(hmenu, media, MF_BYCOMMAND | MF_UNCHECKED);
  1159.     media = new_media;
  1160.     CheckMenuItem(hmenu, media, MF_BYCOMMAND | MF_CHECKED);
  1161.     gswin_resize();
  1162.     return;
  1163. }
  1164.  
  1165. /* go forward skip pages */
  1166. void
  1167. dsc_next(int skip)
  1168. {
  1169.     if (pagenum == doc->numpages || doc->numpages == 0) {
  1170.         play_sound(SOUND_NOPAGE);
  1171.         info_wait(FALSE);
  1172.         return;
  1173.     }
  1174.     pagenum += skip;
  1175.     if (pagenum > doc->numpages)
  1176.          pagenum = doc->numpages;
  1177.     info_wait(TRUE);
  1178.     if (page_ready)
  1179.         next_page();
  1180.     if (gswin_open())
  1181.         return;
  1182.     dsc_dopage();
  1183. }
  1184.  
  1185. /* go back skip pages */
  1186. void
  1187. dsc_prev(int skip)
  1188. {
  1189.     if (pagenum == 1 || doc->numpages == 0) {
  1190.         play_sound(SOUND_NOPAGE);
  1191.         return;
  1192.     }
  1193.     pagenum -= skip;
  1194.     if (pagenum < 1)
  1195.         pagenum = 1;
  1196.     info_wait(TRUE);
  1197.     if (page_ready)
  1198.         next_page();
  1199.     if (gswin_open())
  1200.         return;
  1201.     dsc_dopage();
  1202. }
  1203. /* if no document open, display error message and return true */
  1204. BOOL
  1205. not_open()
  1206. {
  1207.     if (dfname[0] != '\0')
  1208.         return FALSE;
  1209.     gserror(IDS_NOTOPEN, NULL, MB_ICONEXCLAMATION, SOUND_NOTOPEN);
  1210.     return TRUE;
  1211. }
  1212.  
  1213. /* if not DSC document or not open, display error message and return true */
  1214. BOOL
  1215. not_dsc()
  1216. {
  1217.     if (not_open())
  1218.         return TRUE;
  1219.     if (doc!=(struct document *)NULL)
  1220.         return FALSE;
  1221.     gserror(IDS_NOPAGE, NULL, MB_ICONEXCLAMATION, SOUND_NONUMBER);
  1222.     return TRUE;
  1223. }
  1224.  
  1225. void
  1226. gserror(UINT id, char *str, UINT icon, int sound)
  1227. {
  1228. int i;
  1229. char mess[300];
  1230.     if (sound >= 0)
  1231.         play_sound(sound);
  1232.     i = 0;
  1233.     if (id)
  1234.         i = LoadString(phInstance, id, mess, sizeof(mess)-1);
  1235.     mess[i] = '\0';
  1236.     if (str)
  1237.         strncpy(mess+i, str, sizeof(mess)-i-1);
  1238.     MessageBox(hwndimg, mess, szAppName, icon | MB_OK);
  1239. }
  1240.  
  1241. /* for ps.c errors instead of fprintf(stderr,...)! */
  1242. void
  1243. pserror(char *str)
  1244. {
  1245.     MessageBox(hwndimg,str,szAppName, MB_OK | MB_ICONHAND);
  1246. }
  1247.